<template>
  <view class="mode" v-if="isShow">
    <view
      v-if="isShowImg"
      class="uni-corpper"
      :style="
        'width:' +
        cropperInitW +
        'px;height:' +
        cropperInitH +
        'px;background:#000'
      "
    >
      <view
        class="uni-corpper-content"
        :style="
          'width:' +
          cropperW +
          'px;height:' +
          cropperH +
          'px;left:' +
          cropperL +
          'px;top:' +
          cropperT +
          'px'
        "
      >
        <image
          :src="imageSrc"
          :style="'width:' + cropperW + 'px;height:' + cropperH + 'px'"
        />
        <view
          class="uni-corpper-crop-box"
          @touchstart.stop="contentStartMove"
          @touchmove.stop="contentMoveing"
          @touchend.stop="contentTouchEnd"
          :style="
            'left:' +
            CUT_L +
            'px;top:' +
            CUT_T +
            'px;right:' +
            CUT_R +
            'px;bottom:' +
            CUT_B +
            'px'
          "
        >
          <view class="uni-cropper-view-box">
            <view class="uni-cropper-dashed-h"></view>
            <view class="uni-cropper-dashed-v"></view>

            <!-- 截图区域顶部 -->
            <view
              class="uni-cropper-line-t"
              data-drag="top"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>

            <!-- 截图区域右侧 -->
            <view
              class="uni-cropper-line-r"
              data-drag="right"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>

            <!-- 截图区域底部 -->
            <view
              class="uni-cropper-line-b"
              data-drag="bottom"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>

            <!-- 截图区域左侧 -->
            <view
              class="uni-cropper-line-l"
              data-drag="left"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>

            <!-- 右下角截图滑块 -->
            <view
              class="uni-cropper-point point-t"
              data-drag="top"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>
            <view
              class="uni-cropper-point point-tr"
              data-drag="topTight"
            ></view>
            <view
              class="uni-cropper-point point-r"
              data-drag="right"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>
            <view
              class="uni-cropper-point point-rb"
              data-drag="rightBottom"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>
            <view
              class="uni-cropper-point point-b"
              data-drag="bottom"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
              @touchend.stop="dragEnd"
            ></view>
            <view
              class="uni-cropper-point point-bl"
              data-drag="bottomLeft"
            ></view>
            <view
              class="uni-cropper-point point-l"
              data-drag="left"
              @touchstart.stop="dragStart"
              @touchmove.stop="dragMove"
            ></view>
            <view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
          </view>
        </view>
      </view>
    </view>

    <view class="cropper-config">
      <view @click="chooseImage" class="view_btn">重选</view>
      <view @click="finish" class="view_btn">完成</view>
    </view>

    <canvas
      id="myCanvas"
      canvas-id="myCanvas"
      :style="'width:' + imageW + 'px;height:' + imageH + 'px;'"
    ></canvas>
  </view>
</template>

<script setup>
import { ref, defineExpose, defineProps, defineEmits, watch } from "vue";
import { ossImg, oss2, message, debounce } from "@/utils/utils";

const emits = defineEmits(["getImg"]);
const Cropper = ref(null);

let sysInfo = uni.getSystemInfoSync();
let SCREEN_WIDTH = sysInfo.screenWidth;
let SCREEN_HEIGHT = sysInfo.windowHeight + 40;
let DRAFG_MOVE_RATIO = 1; //移动时候的比例,
let DRAW_IMAGE_W = sysInfo.screenWidth; // 设置生成的图片宽度

const isShow = ref(false);
const imageSrc = ref("");
const isShowImg = ref(false);
const tempImage = ref("");
// 初始化的宽高
const cropperInitW = SCREEN_WIDTH;
const cropperInitH = SCREEN_HEIGHT;
// 动态的宽高
const cropperW = ref(SCREEN_WIDTH.screenWidth);
const cropperH = ref(SCREEN_HEIGHT.windowHeight + 40);
// 动态的left top值
const cropperL = ref(0);
const cropperT = ref(0);
// 图片缩放值
const scaleP = ref(0);
const imageW = ref(0);
const imageH = ref(0);
const qualityWidth = ref(DRAW_IMAGE_W);
const innerAspectRadio = ref(DRAFG_MOVE_RATIO);
// 裁剪框 宽高
const CUT_L = ref(0);
const CUT_T = ref(0);
const CUT_B = ref(SCREEN_WIDTH);
const CUT_R = ref("100");
const IMG_RATIO = ref(0);
const IMG_REAL_W = ref(0);
const IMG_REAL_H = ref(0);

const PAGE_X = ref(); // 手按下的x位置
const PAGE_Y = ref(); // 手按下y的位置

/* 选择图片  */
const chooseImage = (cropper, e) => {
  Cropper.value = cropper.value;
  uni.chooseImage({
    count: 1,
    sourceType: ["album"], //从相册选择
    success: (res) => {
      if (res.tempFiles[0].size > 1024 * 1024) {
        message("图片大小不能超过1024KB");
      } else {
        imageSrc.value = res.tempFilePaths[0];
        loadImage();
        isShow.value = true;
      }
    },
  });
};
/* 将图片加载到画布  */
const loadImage = () => {
  //   var _this = this;
  uni.showLoading({
    title: "图片加载中...",
  });

  uni.getImageInfo({
    src: imageSrc.value,
    success: (res) => {
      let imgH = res.height;
      let imgW = res.width;
      /* 图片的宽高比  */
      IMG_RATIO.value = imgW / imgH;

      /**
       * 如果图片更高一些，为确保图片能够完整在视窗内显示需如下处理
       * 1. 缩放图片的高为 视窗高度减去底部菜单按钮高度（120）
       * 2. 根据图片缩放后的高度，根据图片宽高比计算图片的宽度
       * 3. 如果步骤2计算的图片宽度大于屏幕宽度，则需要再次调整图片宽度为视窗宽度-margin(10)
       * 4. 根据步骤3的宽度，结合图片宽高比重新计算图片的高度
       */
      if (
        IMG_RATIO.value < 1 &&
        (SCREEN_HEIGHT - 120) * IMG_RATIO.value < SCREEN_WIDTH - 10
      ) {
        IMG_REAL_W.value = (SCREEN_HEIGHT - 120) * IMG_RATIO.value;
        IMG_REAL_H.value = SCREEN_HEIGHT - 120;
      } else {
        IMG_REAL_W.value = SCREEN_WIDTH - 10;
        IMG_REAL_H.value = IMG_REAL_W.value / IMG_RATIO.value;
      }

      /* 初始化裁剪区域的位置和形状  */
      initCutArea(IMG_RATIO.value, IMG_REAL_H.value, IMG_REAL_W.value);
      /* 裁剪区域的宽高同图片尺寸  */
      cropperW.value = IMG_REAL_W.value;
      cropperH.value = IMG_REAL_H.value;
      /* 上下左右各留一定的margin已便更好的拖动裁剪区域  */
      cropperL.value = Math.ceil((SCREEN_WIDTH - IMG_REAL_W.value) / 2);
      /* 留出底部操作按钮位置 70  */
      cropperT.value = Math.ceil((SCREEN_HEIGHT - IMG_REAL_H.value - 90) / 2);
      // 图片缩放值
      imageW.value = IMG_REAL_W.value;
      imageH.value = IMG_REAL_H.value;
      scaleP.value = IMG_REAL_W.value / SCREEN_WIDTH.value;
      qualityWidth = DRAW_IMAGE_W.valueOf;
      innerAspectRadio = IMG_RATIO.value;

      isShowImg.value = true;
      uni.hideLoading();
    },
  });
};
const initCutArea = (IMG_RATIO, IMG_REAL_H, IMG_REAL_W) => {
  /* 自由裁剪裁剪区域默认覆盖整个图片  */
  let cutT = 0;
  let cutB = 0;
  let cutL = 0;
  let cutR = 0;

  /* 固定比例裁剪，初始化裁剪区域比例和设定值相同  */
  let ratio = 235 / 144;
  if (IMG_RATIO < 1) {
    /* 图片比较高  */
    if (IMG_REAL_W / ratio > IMG_REAL_H) {
      cutT = cutB = 0;
      cutL = cutR = (IMG_REAL_W - IMG_REAL_H * ratio) / 2;
    } else {
      cutR = cutL = 0;
      cutT = cutB = (IMG_REAL_H - IMG_REAL_W / ratio) / 2;
    }
  } else {
    /* 图片比较宽  */
    if (IMG_REAL_H * ratio > IMG_REAL_W) {
      cutL = cutR = 0;
      cutB = cutT = (IMG_REAL_H - IMG_REAL_W / ratio) / 2;
    } else {
      cutT = cutB = 0;
      cutL = cutR = (IMG_REAL_W - IMG_REAL_H * ratio) / 2;
    }
  }
  CUT_T.value = cutT;
  CUT_B.value = cutB;
  CUT_L.value = cutL;
  CUT_R.value = cutR;
};

// 拖动时候触发的touchStart事件
const contentStartMove = (e) => {
  PAGE_X.value = e.touches[0].pageX;
  PAGE_Y.value = e.touches[0].pageY;
};
// 拖动时候触发的touchMove事件
const contentMoveing = (e) => {
  var dragLengthX = (PAGE_X.value - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
  var dragLengthY = (PAGE_Y.value - e.touches[0].pageY) * DRAFG_MOVE_RATIO;

  if (dragLengthX > 0) {
    if (CUT_L.value - dragLengthX < 0) dragLengthX = CUT_L.value;
  } else {
    if (CUT_R.value + dragLengthX < 0) dragLengthX = -CUT_R.value;
  }
  if (dragLengthY > 0) {
    if (CUT_T.value - dragLengthY < 0) dragLengthY = CUT_T.value;
  } else {
    if (CUT_B.value + dragLengthY < 0) dragLengthY = -CUT_B.value;
  }

  CUT_L.value = CUT_L.value - dragLengthX;
  CUT_T.value = CUT_T.value - dragLengthY;
  CUT_R.value = CUT_R.value + dragLengthX;
  CUT_B.value = CUT_B.value + dragLengthY;

  PAGE_X.value = e.touches[0].pageX;
  PAGE_Y.value = e.touches[0].pageY;
};

/* 完成裁剪，输出裁剪后的图片路径  */
const finish = () => {
  uni.showLoading({
    title: "图片生成中...",
  });
  // 将图片写入画布
  const ctx = uni.createCanvasContext("myCanvas", Cropper.value);
  ctx.drawImage(imageSrc.value, 0, 0, IMG_REAL_W.value, IMG_REAL_H.value);
  ctx.draw(
    false,
    // (res) => {
    setTimeout(() => {
      // 获取画布要裁剪的位置和宽度   均为百分比 * 画布中图片的宽度    保证了在微信小程序中裁剪的图片模糊  位置不对的问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
      var canvasW =
        ((cropperW.value - CUT_L.value - CUT_R.value) / cropperW.value) *
        IMG_REAL_W.value;
      var canvasH =
        ((cropperH.value - CUT_T.value - CUT_B.value) / cropperH.value) *
        IMG_REAL_H.value;
      var canvasL = (CUT_L.value / cropperW.value) * IMG_REAL_W.value;
      var canvasT = (CUT_T.value / cropperH.value) * IMG_REAL_H.value;

      return new Promise((resolve, reject) => {
        try {
          uni.canvasToTempFilePath(
            {
              x: canvasL,
              y: canvasT,
              width: canvasW,
              height: canvasH,
              quality: 1,
              canvasId: "myCanvas",
              success: (fileRes) => {
                // tempImage.value = fileRes.tempFilePath;
                compressImage(fileRes.tempFilePath);
                // emits("getImg", imageUrl);
                // isShow.value = false;
                // uni.hideLoading();
                resolve(fileRes.tempFilePath);
              },
              fail: (err) => {
                uni.hideLoading();
                uni.showToast({
                  title: "图片截取失败！",
                  icon: "none",
                });
                isShow.value = false;
                reject();
              },
            },
            Cropper.value
          );
        } catch (e) {
          reject(e);
        }
      });
    }, 500)
  );
};

const compressImage = (url) => {
  return new Promise((resolve, reject) => {
    uni.getFileInfo({
      filePath: url,
      success: async (info) => {
        console.log(info.size);
        if (info.size < 1024 * 1024) {
          emits("getImg", url);
          isShow.value = false;
          uni.hideLoading();
          resolve(url);
          return;
        }
        uni.compressImage({
          src: url,
          quality: 80,
          success: (res) => {
            compressImage(res.tempFilePath);
          },
        });
      },
    });
  });
  console.log("sssss", url);
  uni.getFileInfo({
    filePath: url,
    success: (imgInfo) => {
      console.log(imgInfo.size);
      if (imgInfo.size < 1024 * 1024) {
        return url;
      }
      uni.compressImage({
        src: fileRes.tempFilePath,
        quality: 80,
        success: (res) => {
          console.log("eeeeeeeeeeeee", res.tempFilePath);
          compressImage(res.tempFilePath);
        },
      });
    },
  });
};

defineExpose({
  chooseImage,
});
</script>

<style lang="less" scoped>
@import "@/static/css/theme.less";
.mode {
  width: 100%;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 98;
  background-color: rgba(0, 0, 0, 0.7);
  .uni-corpper {
    position: relative;
    overflow: hidden;
    box-sizing: border-box;
    margin: 0 auto;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    -webkit-touch-callout: none;
  }
  .uni-corpper-content {
    position: relative;
  }
  /* 内部的信息 */
  .uni-corpper-crop-box {
    position: absolute;
    z-index: 2;
    max-height: calc(100vh - 100upx);
    background: rgba(56, 50, 50, 0.479);
  }
  .uni-corpper-crop-box .uni-cropper-view-box {
    position: relative;
    display: block;
    overflow: visible;
    width: 100%;
    height: 100%;
    max-height: calc(100vh - 100upx);
    outline: 5upx solid rgb(100, 97, 97);
    outline-color: rgba(255, 255 255, 1);
  }
  /* 横向虚线 */
  .uni-cropper-dashed-h {
    position: absolute;
    top: 33.33333333%;
    left: 0;
    width: 100%;
    height: 33.33333333%;
    border-top: 1upx dashed rgba(255, 255, 255, 0.5);
    border-bottom: 1upx dashed rgba(255, 255, 255, 0.5);
  }

  /* 纵向虚线 */
  .uni-cropper-dashed-v {
    position: absolute;
    top: 0;
    left: 33.33333333%;
    width: 33.33333333%;
    height: 100%;
    border-right: 1upx dashed rgba(255, 255, 255, 0.5);
    border-left: 1upx dashed rgba(255, 255, 255, 0.5);
  }
  /* 四个方向的线  为了之后的拖动事件*/
  .uni-cropper-line-t {
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    width: 100%;
    height: 3upx;
    cursor: n-resize;
    opacity: 0.1;
    background-color: white;
  }

  .uni-cropper-line-t::before {
    position: absolute;
    z-index: 11;
    top: 50%;
    right: 0upx;
    bottom: 0;
    width: 100%;
    height: 41upx;
    content: "";
    -webkit-transform: translate3d(0, -50%, 0);
    transform: translate3d(0, -50%, 0);
    background: transparent;
  }
  .uni-cropper-line-r {
    position: absolute;
    top: 0;
    right: 0upx;
    display: block;
    width: 3upx;
    height: 100%;
    cursor: e-resize;
    opacity: 0.1;
    background-color: white;
  }

  .uni-cropper-line-r::before {
    position: absolute;
    z-index: 11;
    top: 0;
    bottom: 0;
    left: 50%;
    width: 41upx;
    height: 100%;
    content: "";
    -webkit-transform: translate3d(-50%, 0, 0);
    transform: translate3d(-50%, 0, 0);
    background: transparent;
  }
  .uni-cropper-line-b {
    position: absolute;
    bottom: 0;
    left: 0;
    display: block;
    width: 100%;
    height: 3upx;
    cursor: s-resize;
    opacity: 0.1;
    background-color: white;
  }
  .uni-cropper-line-b::before {
    position: absolute;
    z-index: 11;
    top: 50%;
    right: 0upx;
    bottom: 0;
    width: 100%;
    height: 41upx;
    content: "";
    -webkit-transform: translate3d(0, -50%, 0);
    transform: translate3d(0, -50%, 0);
    background: transparent;
  }
  .uni-cropper-line-l {
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    width: 3upx;
    height: 100%;
    cursor: w-resize;
    opacity: 0.1;
    background-color: white;
  }

  .uni-cropper-line-l::before {
    position: absolute;
    z-index: 11;
    top: 0;
    bottom: 0;
    left: 50%;
    width: 41upx;
    height: 100%;
    content: "";
    -webkit-transform: translate3d(-50%, 0, 0);
    transform: translate3d(-50%, 0, 0);
    background: transparent;
  }

  .cropper-config {
    position: fixed;
    z-index: 999;
    bottom: 60px;
    left: 0;
    right: 0;
    width: 90%;
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    .view_btn {
      width: 45px;
      height: 18px;
      text-align: center;
      line-height: 18px;
      font-family: Source Han Sans CN;
      font-weight: 400;
      font-size: 14px;
      color: #fff;
    }
  }
}
</style>